<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { Modal, Tree, message } from 'ant-design-vue'
import type { TreeProps } from 'ant-design-vue'
import { tree } from '~@/api/menu/menu'
import { batchUpdateApi, getUserRoleListApi } from '~@/api/menu/role-menu'
import type { MenuModel } from '~@/api/menu/menu'

const props = defineProps<{
  roleId: number | string
  visible: boolean
  onClose: () => void
  onSuccess: () => void
}>()

const emit = defineEmits<{
  (e: 'update:visible', value: boolean): void
  (e: 'success'): void
}>()

const treeData = ref<MenuModel[]>([])
const checkedKeys = ref<number[]>([])
const loading = ref(false)
// 添加一个标志来跟踪组件是否已卸载
const isUnmounted = ref(false)

// 关闭弹窗
function handleClose() {
  emit('update:visible', false)
}

async function getMenuTree() {
  loading.value = true
  try {
    const { data } = await tree()
    if (isUnmounted.value)
      return

    if (Array.isArray(data.list)) {
      treeData.value = data.list
      console.log('菜单树数据加载成功:', treeData.value)
    }
    else {
      treeData.value = []
      console.error('获取的菜单树数据不是数组:', data)
      message.error('获取的菜单树数据格式不正确')
    }

    // 确保treeData已经更新后再获取角色菜单
    await nextTick()
    await getRoleMenus()
  }
  catch (error) {
    if (isUnmounted.value)
      return
    console.error('获取菜单树失败:', error)
    message.error('获取菜单树失败')
  }
  finally {
    if (isUnmounted.value)
      return
    loading.value = false
  }
}

const fieldNames: TreeProps['fieldNames'] = {
  key: 'menuId',
  title: 'menuName',
}

// 获取角色已绑定的菜单
async function getRoleMenus() {
  try {
    const { data } = await getUserRoleListApi(Number(props.roleId))
    if (isUnmounted.value)
      return

    // 确保checkedKeys始终是数组
    let menuIds: string[] = []

    // 检查数据格式
    if (data && Array.isArray(data)) {
      // 提取menuId并转换为字符串
      menuIds = data.map((item) => {
        const id = item.menuId
        // 确保id是字符串类型
        return id !== undefined ? String(id) : ''
      }).filter(Boolean)
    }
    else {
      console.error('获取的角色菜单数据格式不正确:', data)
      message.warning('获取的角色菜单数据格式不正确')
    }

    // 确保赋值为数组
    checkedKeys.value = menuIds.map(Number)
  }
  catch (error) {
    if (isUnmounted.value)
      return
    console.error('获取角色菜单失败:', error)
    message.error('获取角色菜单失败')
  }
}

// 提交角色菜单绑定
async function handleSubmit() {
  loading.value = true
  try {
    const formState = {
      roleId: Number(props.roleId),
      menuIds: checkedKeys.value.map(id => Number(id)),
    }
    // 使用JSON格式提交，确保数组能被后端正确接收
    await batchUpdateApi(formState, { headers: { 'Content-Type': 'application/json' } })
    if (isUnmounted.value)
      return
    message.success('角色菜单绑定成功')
    emit('success')
    emit('update:visible', false)
  }
  catch (error) {
    if (isUnmounted.value)
      return
    console.error('角色菜单绑定失败:', error)
    message.error('角色菜单绑定失败')
  }
  finally {
    if (isUnmounted.value)
      return
    loading.value = false
  }
}

onMounted(() => {
  isUnmounted.value = false
})

onUnmounted(() => {
  isUnmounted.value = true
})

// 监听弹窗可见性变化，当打开时刷新角色菜单
watch(() => props.visible, (newVisible) => {
  if (newVisible) {
    // 先重置选中状态
    checkedKeys.value = []
    getMenuTree()
  }
})
</script>

<template>
  <a-modal
    v-model:visible="props.visible"
    title="绑定菜单"
    :loading="loading"
    @cancel="handleClose"
  >
    <template #footer>
      <a-button @click="handleClose">
        取消
      </a-button>
      <a-button type="primary" @click="handleSubmit">
        确认绑定
      </a-button>
    </template>
    <a-tree
      v-model:checked-keys="checkedKeys"
      :field-names="fieldNames"
      :selected-keys="checkedKeys"
      :tree-data="treeData"
      checkable
      default-expand-all
    />
  </a-modal>
</template>
